home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
pascal
/
grabkey.exe
/
GRABKEY.PAS
Wrap
Pascal/Delphi Source File
|
1991-07-10
|
4KB
|
137 lines
{ To Dave Tipton
Example of an interrupt to grab the scan code of each key pressed -
but not to eat the key. Pass the interrupt back to DOS so it can
do what it does.
You'll need a look-Up table for the scan codes.
OR - you could eat the key - and then put it back with
TURBO PROFESSIONAL's Stuff Key. Play around with it.
Compile this and run it. 'Q' Quits. Good Luck.
}
PROGRAM GrabKeys;
{ !! Keep F+ and B- for INTERRUPT and FAST Bit testing !! }
{$F+,B-}
{$R-,I-,S-,L-,D-}
{ 18 June 91 }
{ J. Dennis Green - 71620,2427 : Intercept and reRoute Key }
USES
TpCRT, { TURBO PROFESSIONAL's CRT or CRT }
DOS; { For Registers, Interrupt, Error }
CONST
Key_Int = $09;
Key_Vec : Pointer = NIL; { Swap Key Interrupt }
Exit_Save : Pointer = NIL; { Swap exit procedure }
xKey : Word = 0;
RShift = 1; { Constants for Bit Testing xShift }
LShift = 2;
CtrlShift = 4;
AltShift = 8;
ScrollLock = 16;
NumLock = 32;
CapsLock = 64;
InsertLock = 128;
VAR
ch : Char;
xShift : Byte Absolute $0040:$0017; { THE information }
xExtended : Boolean;
{ Grab the keyboard interrupt, retrieve the scancode }
PROCEDURE GrabKey ( Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : Word );
INTERRUPT;
BEGIN
{ Read the key directly - but don't eat it }
xKey:= PortW[$60];
{ Give it back }
InLine
(
$FB/ { Interrupts On }
$A1/>Key_Vec+2/ { Mov AX, [>Key_Vec+2] }
{ Old Vector Seg to AX }
$8B/$1E/>Key_Vec/ { Mov BX, [>Key_Vec] }
{ Old Vector Ofs to BX }
$87/$5E/$0E/ { XCHG BX,[BP+$0E] }
{ Swap Ofs w/ Return address }
$87/$46/$10/ { Xchg AX,[BP+$10] }
{ Swap Set w/ Return address }
$89/$EC/ { Mov SP,BP ; Undo entry code }
$5D/ { POP BP }
$07/ { POP ES }
$1F/ { POP DS }
$5F/ { POP DI }
$5E/ { POP SI }
$5A/ { POP DX }
$59/ { POP CX }
$CB ); { RETF ; In effect JMP to old vector }
END;
{ Restore the original Key Interrupt }
PROCEDURE MyExit;
BEGIN
ExitProc:= Exit_Save; { Restore normal Exit Procedure }
InLine ($9C/$FA); { PushF, Cli }
SetIntVec (Key_Int, Key_Vec ); { Restore original Key interrupt }
InLine ($FB/$9D); { Sti, Pop Flags }
END;
{ Simple example to test for Shifted stuff }
FUNCTION Shifted: Boolean;
BEGIN
Shifted:= ( (xShift and RShift = RShift) or
(xShift and LShift = LShift) or
(xShift and CapsLock = CapsLock) );
END;
BEGIN
GetIntVec (Key_Int, Key_Vec); { Get and Save Key interrupt }
InLine ($FA); { Stop Interrupts }
SetIntVec (Key_Int, @GrabKey); { ReRoute it to 'my' KeyRead }
InLine ($FB); { Allow Interrupts }
Exit_Save:= ExitProc; { Get and Save normal Exit procedure }
ExitProc := @MyExit; { ReRoute it to 'my' Exit }
{ Main Program }
REPEAT
IF KeyPressed THEN
BEGIN
{ Lo(xKey) is ScanCode - See TP6 Table B.3 / TP5.5 Table C.3 }
{ xShift is the keyboard Status }
{ Writing CH just for checking }
{ Note that Special Keys - (HOME) - hits this twice. }
{ - xExtended is shown. See ReadKey Explanation }
Write ( Lo(xKey):5, xShift:5, ' ',Shifted,' -> ');
Ch:= ReadKey;
IF (Ch = 'Q') THEN Halt(0);
xExtended:= (Ch = #0);
Writeln ( ch, ' ', xExtended );
END;
UNTIL False;
END.